﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Extensions;

namespace MetaSharp.Transformation.Grammar.Tests.TokenizerTests
{
    public class CommentTests
    {
        Tokenizer tokenizer = new Tokenizer();

        [Theory]
        [InlineData("//")]
        [InlineData("//xyz")]
        [InlineData("// xyz")]
        [InlineData("///")]
        [InlineData("////")]
        [InlineData("// a // b")]
        [InlineData("///**/")]
        public void CanParseValidSingleLineComment(string comment)
        {
            var p = tokenizer.SingleLineComment.ToPatternMatch();
            var s = new Scope(new Stream(comment));
            var m = p(s);

            Assert.True(m.Matched);
        }

        [Theory]
        [InlineData(@"/ /")]
        [InlineData(@"/")]
        [InlineData(@"\\")]
        public void DoesntParseInvalidSingleLineComment(string notcomment)
        {
            var p = tokenizer.SingleLineComment.ToPatternMatch();
            var s = new Scope(new Stream(notcomment));
            var m = p(s);

            Assert.False(m.Matched);
        }

        [Theory]
        [InlineData('\r')]
        [InlineData('\n')]
        [InlineData('\u0085')]
        [InlineData('\u2028')]
        [InlineData('\u2029')]
        public void SingleLineCommentDoesntConsumeNewLineCharacter(char newline)
        {
            var c = "//" + newline;
            var p = Pattern.And(
                tokenizer.SingleLineComment,
                Pattern.Value(newline))
                .ToPatternMatch();

            var s = new Scope(new Stream(c));
            var m = p(s);

            Assert.True(m.Matched);
        }

        [Fact]
        public void SingleLineCommentDoesntConsumeLineFeedCarriageReturn()
        {
            var c = "//\r\n";
            var p = Pattern.And(
                tokenizer.SingleLineComment,
                Pattern.Value('\r'),
                Pattern.Value('\n'))
                .ToPatternMatch();

            var s = new Scope(new Stream(c));
            var m = p(s);

            Assert.True(m.Matched);
        }

        [Theory]
        [InlineData("/**/")]
        [InlineData("/* */")]
        [InlineData("/***/")]
        [InlineData("/* * / */")]
        [InlineData("/*//*/")]
        public void CanParseDelimitedComments(string comment)
        {
            var p = tokenizer.DelimitedComment.ToPatternMatch();
            var s = new Scope(new Stream(comment));
            var m = p(s);

            Assert.True(m.Matched);
        }
    }
}
